package protocol;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

import forumSystem.ForumSystemImpl;
import forumSystem.Pair;
import forumSystem.Reply;
import forumSystem.User;

import msgParser.Functions;
import msgParser.Message;
import msgParser.Parser;
import msgParser.Strings;

import reactor.ConnectionHandler;
import reactor.Reactor;
import tokenizer.http.*;

/**
 * a simple implementation of the server protocol interface
 */
public class HttpProtocol implements AsyncServerProtocol<HttpMessage> 
{
	private final static String error404;
	private final static byte forumsystem_html[]=new byte[63122];
	private final static byte forum_entry_html[]=new byte[63122];
	private final static byte topic_html[]=new byte[63122];
	private final static byte message_html[]=new byte[63122];
	private final static byte new_topic_html[]=new byte[63122];
	private final static byte new_reply_html[]=new byte[63122];
	private final static byte subforum_entry_html[]=new byte[63122];
	private final static byte topic_entry_html[]=new byte[63122];
	private final static byte style_css[]=new byte[63122];
	private final static byte logo_png[]=new byte[63122];
	private final static byte post_reply_png[]=new byte[63122];
	private final static byte forum_png[]=new byte[63122];
	private final static byte subforum_html[]=new byte[63122];
	private final static byte loginsystem_html[]=new byte[63122];
	private final static byte login_html[]=new byte[63122];
	private final static byte new_post_png[]=new byte[63122];
	private final static byte logout_html[]=new byte[63122];
	
	private boolean _shouldClose = false;
	private boolean _connectionTerminated = false;

	private TreeMap<String, String> session;
	private ForumProtocol forumProtocol;
	
	public HttpProtocol(TreeMap<String, String> connectionRecord)
	{
		this.session=connectionRecord;
		forumProtocol = new ForumProtocol(connectionRecord);
		//log = new ForumLogger();
	}
	
	/**
	 *  This is a static constructor that initialize the static fields.
	 */
	static
	{
		error404="<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title>HTTP/1.1 404 Not Found</title></head><body>To get the sample picture click <a href=\"pic\">here - GET /pic HTTP/1.1</a><br/>To get the sample XML file click <a href=\"xml\">here - GET /xml HTTP/1.1</a><br/>To upload a picture use <b>curl -H \"content-type: image/jpg\" -T image1.jpg [server-address]/pic > image2.jpg</b> request<br/>To upload an XML file use <b>curl -H \"content-type: text/xml\" -T job1.xml [server-address]/xml >job2.xml</b> request<br/></body></html>";
		try {
			File file;
			FileInputStream fis; 
				
			
			file = new File("forumsystem.html");
			fis = new FileInputStream(file);
			fis.read(forumsystem_html);
			fis.close();
			
			file = new File("forum_entry.html");
			fis = new FileInputStream(file);
			fis.read(forum_entry_html);
			fis.close();

			file = new File("subforum_entry.html");
			fis = new FileInputStream(file);
			fis.read(subforum_entry_html);
			fis.close();
			
			file = new File("logout.html");
			fis = new FileInputStream(file);
			fis.read(logout_html);
			fis.close();

			file = new File("topic_entry.html");
			fis = new FileInputStream(file);
			fis.read(topic_entry_html);
			fis.close();
			
			file = new File("loginsystem.html");
			fis = new FileInputStream(file);
			fis.read(loginsystem_html);
			fis.close();
			
			file = new File("new_topic.html");
			fis = new FileInputStream(file);
			fis.read(new_topic_html);
			fis.close();
			
			file = new File("login.html");
			fis = new FileInputStream(file);
			fis.read(login_html);
			fis.close();
			
			file = new File("new_reply.html");
			fis = new FileInputStream(file);
			fis.read(new_reply_html);
			fis.close();
			
			file = new File("post_reply.png");
			fis = new FileInputStream(file);
			fis.read(post_reply_png);
			fis.close();
			
			file = new File("new_post.png");
			fis = new FileInputStream(file);
			fis.read(new_post_png);
			fis.close();
			
			file = new File("topic.html");
			fis = new FileInputStream(file);
			fis.read(topic_html);
			fis.close();
			
			file = new File("message.html");
			fis = new FileInputStream(file);
			fis.read(message_html);
			fis.close();

			file = new File("subforum.html");
			fis = new FileInputStream(file);
			fis.read(subforum_html);
			fis.close();
			
			file = new File("style.css");
			fis = new FileInputStream(file);
			fis.read(style_css);
			fis.close();
			
			file = new File("logo.png");
			fis = new FileInputStream(file);
			fis.read(logo_png);
			fis.close();
			
			file = new File("forum.png");
			fis = new FileInputStream(file);
			fis.read(forum_png);
			fis.close();
			
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
		
	}
	
	
	public HttpMessage processMessage(HttpMessage msg, ConnectionHandler ch) 
	{     
		HttpRequestMessage request=(HttpRequestMessage)msg;
		
		HttpResponseCode code=null;
		String protocol="HTTP/1.1";
		Map<String, List<String>> headers=new Hashtable<String, List<String>>();
		ByteBuffer body=null;
		
		if (this._connectionTerminated) 
		{
			return null;
		}
		
		if (this.isEnd(msg)) 
		{
			this._shouldClose = true;
		}
		//System.out.println("HEADERS");
		//System.out.println(msg.headers);
		List<String> cookie_list = msg.headers.get("cookie");
		//System.out.println(cookie_list);
		
		if(cookie_list != null)
		{
			String cookie = cookie_list.get(0);
			int idx = cookie.indexOf('=');
			String sessionCode = cookie.substring(idx+1);
			//System.out.println("SessionCode");
			//System.out.println(sessionCode);
			int dotpos = sessionCode.indexOf('.');
			if(dotpos != -1 && dotpos+1 < sessionCode.length())
			{
				String userId = sessionCode.substring(0, dotpos);
				String verification = sessionCode.substring(dotpos+1);
				//time to verify
				User u = ForumSystemImpl.getUserByID(Integer.parseInt(userId));
				if(u != null && verification.equals(Functions.md5(u.getUsername() + u.getPass())))
				{
					session.put("userID", userId);
					//System.out.println("User Recognized :)");
				}
				else 
				{
					//System.out.println("Verification fail");
					//System.out.println("REG:"+u.getUsername() + u.getPass());
					//System.out.println(Functions.md5(u.getUsername() + u.getPass()));
					//System.out.println(verification);
				}
			}
			//else System.out.println("corrupt fail");
		}
		switch (request.operator)
		{
			case POST:
				if(request.URI.startsWith("/postreply/"))
				{
					int topicId = Integer.parseInt(request.URI.substring(11));
					String content = new String(request.body.array());
					if(!content.startsWith("message=")) break;
					String message = content.indexOf('&') == -1 ? content.substring(8) : content.substring(8, content.indexOf('&'));
					//System.out.println("Message is " + message);
					try 
					{
						message = URLDecoder.decode(message, "UTF-8");
					} catch (UnsupportedEncodingException e) {}
					
					code=HttpResponseCode.S200;
					String postReplyPage = postReplyPage(ch, topicId, message);
					body=ByteBuffer.wrap(postReplyPage.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + postReplyPage.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
				}
				else if(request.URI.startsWith("/newtopic/"))
				{
					int subForumId = Integer.parseInt(request.URI.substring(10));
					String content = new String(request.body.array());
					System.out.println("CONTENT");
					System.out.println(content);
					if(!content.startsWith("subject=")) break;
					int subjectpos = content.indexOf("subject=");
					int messagepos = content.indexOf("message=");
					String subject = content.substring(subjectpos+8, content.indexOf('&'));
					String message = content.substring(messagepos+8, messagepos+content.substring(messagepos).indexOf('&'));
					try 
					{
						message = URLDecoder.decode(message, "UTF-8");
					} catch (UnsupportedEncodingException e) {}
					try 
					{
						subject = URLDecoder.decode(subject, "UTF-8");
					} catch (UnsupportedEncodingException e) {}
					code=HttpResponseCode.S200;
					String newTopicPage = newTopicPage(ch, subForumId, subject, message);
					body=ByteBuffer.wrap(newTopicPage.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + newTopicPage.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
				}
				else if(request.URI.equals("/logout"))
				{
					
					String content = new String(request.body.array());
					
					int x4 = content.indexOf("redirect=")+9;
					String redirect = content.substring(x4);
					try {
						redirect = URLDecoder.decode(redirect, "UTF-8");
					} catch (UnsupportedEncodingException e) {
						
					}
					
					
					boolean ans = logout(ch);
					if(!ans)
					{
						String protocol2="HTTP/1.1";
						Map<String, List<String>> headers2=new Hashtable<String, List<String>>();
						ByteBuffer body2 = null;
						HttpMessage m = new HttpRequestMessage(HttpOperator.GET, redirect, protocol2, headers2, body2);
						HttpMessage res = processMessage(m, ch);
						String body_ans = new String(res.body.array());
						//body_ans = body_ans.substring(0, body_ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\".\");</script></body></html>";
						res.body = ByteBuffer.wrap(body_ans.getBytes());
						return (HttpResponseMessage)res;
					}
					else
					{
						String protocol2="HTTP/1.1";
						Map<String, List<String>> headers2=new Hashtable<String, List<String>>();
						ByteBuffer body2=null;
						HttpMessage m = new HttpRequestMessage(HttpOperator.GET, redirect, protocol2, headers2, body2);
						HttpMessage res = processMessage(m, ch);
						HttpMessage.addHeader(res.headers, "Set-Cookie: sessionCode=null");
						
						return (HttpResponseMessage)res;
					}
				}
				else if(request.URI.equals("/login"))
				{
					
					String content = new String(request.body.array());
					
					int x1 = content.indexOf("username=")+9;
					String userName = content.substring(x1, content.substring(x1).indexOf('&')+x1);
					
					int x2 = content.indexOf("password=")+9;
					String userPass = content.substring(x2, content.substring(x2).indexOf('&')+x2);
					
					int x3 = content.indexOf("forumid=")+8;
					String forumId = content.substring(x3, content.substring(x3).indexOf('&')+x3);
					
					int x4 = content.indexOf("redirect=")+9;
					String redirect = content.substring(x4);
					try {
						redirect = URLDecoder.decode(redirect, "UTF-8");
					} catch (UnsupportedEncodingException e) {
						
					}
					
					//System.out.println("DATA: ");
					//System.out.println(userName);
					//System.out.println(userPass);
					//System.out.println(forumId);
					//System.out.println(redirect);
					
					boolean ans = login(ch, userName, userPass, forumId);
					if(!ans)
					{
						String protocol2="HTTP/1.1";
						Map<String, List<String>> headers2=new Hashtable<String, List<String>>();
						ByteBuffer body2 = null;
						HttpMessage m = new HttpRequestMessage(HttpOperator.GET, redirect, protocol2, headers2, body2);
						HttpMessage res = processMessage(m, ch);
						String body_ans = new String(res.body.array());
						body_ans = body_ans.substring(0, body_ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\"Wrong user name or password. Try again.\");</script></body></html>";
						res.body = ByteBuffer.wrap(body_ans.getBytes());
						return (HttpResponseMessage)res;
					}
					else
					{
					
						String protocol2="HTTP/1.1";
						Map<String, List<String>> headers2=new Hashtable<String, List<String>>();
						ByteBuffer body2=null;
						HttpMessage m = new HttpRequestMessage(HttpOperator.GET, redirect, protocol2, headers2, body2);
						String sessionCode = generateSession(userName, userPass);
						HttpMessage res = processMessage(m, ch);
						HttpMessage.addHeader(res.headers, "Set-Cookie: sessionCode=" + session.get("userID") + "." + sessionCode);
						return (HttpResponseMessage)res;
					}
				}
				else if(request.URI.startsWith("/login/"))
				{
					
					String content = new String(request.body.array());
					
					int x1 = content.indexOf("username=")+9;
					String userName = content.substring(x1, content.substring(x1).indexOf('&')+x1);
					
					int x2 = content.indexOf("password=")+9;
					String userPass = content.substring(x2, content.substring(x2).indexOf('&')+x2);
					
					//int x3 = content.indexOf("forumid=")+8;
					String forumId = request.URI.substring(7);
					
					int x4 = content.indexOf("redirect=")+9;
					String redirect = content.substring(x4);
					try {
						redirect = URLDecoder.decode(redirect, "UTF-8");
					} catch (UnsupportedEncodingException e) {
						
					}
					
					//System.out.println("DATA: ");
					//System.out.println(userName);
					//System.out.println(userPass);
					//System.out.println(forumId);
					//System.out.println(redirect);
					
					boolean ans = login(ch, userName, userPass, forumId);
					if(!ans)
					{
						String protocol2="HTTP/1.1";
						Map<String, List<String>> headers2=new Hashtable<String, List<String>>();
						ByteBuffer body2 = null;
						HttpMessage m = new HttpRequestMessage(HttpOperator.GET, redirect, protocol2, headers2, body2);
						HttpMessage res = processMessage(m, ch);
						String body_ans = new String(res.body.array());
						body_ans = body_ans.substring(0, body_ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\"Wrong user name or password. Try again.\");</script></body></html>";
						res.body = ByteBuffer.wrap(body_ans.getBytes());
						return (HttpResponseMessage)res;
					}
					else
					{
						System.out.println("LOGGED IN :)");
						String protocol2="HTTP/1.1";
						Map<String, List<String>> headers2=new Hashtable<String, List<String>>();
						ByteBuffer body2=null;
						HttpMessage m = new HttpRequestMessage(HttpOperator.GET, redirect, protocol2, headers2, body2);
						String sessionCode = generateSession(userName, userPass);
						HttpMessage res = processMessage(m, ch);
						HttpMessage.addHeader(res.headers, "Set-Cookie: sessionCode=" + session.get("userID") + "." + sessionCode);
						return (HttpResponseMessage)res;
					}
				}
				else
				{
					System.out.println("unknown post: " + request.URI);
					code=HttpResponseCode.S404; //The default answer - an HTML page
					byte bytes[]=error404.getBytes(Charset.forName("UTF-8"));
					HttpMessage.addHeader(headers, "Content-length: " + bytes.length);
					HttpMessage.addHeader(headers, "Content-type: text/html; charset=utf-8");
					body=ByteBuffer.wrap(bytes);
				}
				
				break;
			case GET:
				if(request.URI.endsWith("/style.css"))
				{ 
					code=HttpResponseCode.S200;
					HttpMessage.addHeader(headers, "Content-length: " + style_css.length);
					HttpMessage.addHeader(headers, "Content-type: text/css");
					body=ByteBuffer.wrap(style_css);
				}
				else if(request.URI.equals("/logo.png"))
				{ 
					code=HttpResponseCode.S200;
					HttpMessage.addHeader(headers, "Content-length: " + logo_png.length);
					HttpMessage.addHeader(headers, "Content-type: image/png");
					body=ByteBuffer.wrap(logo_png);
				}
				else if(request.URI.equals("/new_post.png"))
				{ 
					code=HttpResponseCode.S200;
					HttpMessage.addHeader(headers, "Content-length: " + new_post_png.length);
					HttpMessage.addHeader(headers, "Content-type: image/png");
					body=ByteBuffer.wrap(new_post_png);
				}
				else if(request.URI.equals("/forum.png"))
				{ 
					code=HttpResponseCode.S200;
					HttpMessage.addHeader(headers, "Content-length: " + forum_png.length);
					HttpMessage.addHeader(headers, "Content-type: image/png");
					body=ByteBuffer.wrap(forum_png);
				}
				else if(request.URI.equals("/post_reply.png"))
				{ 
					code=HttpResponseCode.S200;
					HttpMessage.addHeader(headers, "Content-length: " + post_reply_png.length);
					HttpMessage.addHeader(headers, "Content-type: image/png");
					body=ByteBuffer.wrap(post_reply_png);
				}
				
				/*
				else if(request.URI.equals("/xml"))
				{ // The default XML message
					code=HttpResponseCode.S200;
					byte bytes[]=sample_xml.getBytes(Charset.forName("UTF-8"));
					HttpMessage.addHeader(headers, "Content-length: " + bytes.length);
					HttpMessage.addHeader(headers, "Content-type: text/xml; charset=utf-8");
					
					body=ByteBuffer.wrap(bytes);
				}
				*/
				else if(request.URI.equals("/") || request.URI.equals("") || request.URI.equals("/index.html"))
				{
					code=HttpResponseCode.S200;
					String bodyStr = getForumSystemPage(ch);
					body=ByteBuffer.wrap(bodyStr.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + bodyStr.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
					
					
				}
				else if(request.URI.startsWith("/subforum/"))
				{
					code=HttpResponseCode.S200;
					String idstr = request.URI.substring(10);
					int id = Integer.parseInt(idstr);
					
					String subForumPage = getSubForumPage(ch, id);
					body=ByteBuffer.wrap(subForumPage.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + subForumPage.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
					
				}
				else if(request.URI.startsWith("/topic/"))
				{
					code=HttpResponseCode.S200;
					String idstr = request.URI.substring(7);
					int id = Integer.parseInt(idstr);
					String topicPage = getTopicPage(ch, id);
					body=ByteBuffer.wrap(topicPage.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + topicPage.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
				}
				else if(request.URI.startsWith("/newtopic/"))
				{
					code=HttpResponseCode.S200;
					String idstr = request.URI.substring(10);
					int id = Integer.parseInt(idstr);
					String newTopicPage = getNewTopicPage(ch, id);
					body=ByteBuffer.wrap(newTopicPage.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + newTopicPage.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
				}
				else if(request.URI.startsWith("/postreply/"))
				{
					code=HttpResponseCode.S200;
					String idstr = request.URI.substring(11);
					int id = Integer.parseInt(idstr);
					String newReplyPage = getNewReplyPage(ch, id);
					body=ByteBuffer.wrap(newReplyPage.getBytes());
					HttpMessage.addHeader(headers, "Content-length: " + newReplyPage.length());
					HttpMessage.addHeader(headers, "Content-type: text/html");
				}
				else
				{
					System.out.println("Failed to fetch resource - " + request.URI);
					code=HttpResponseCode.S404; //The default answer - an HTML page
					byte bytes[]=error404.getBytes(Charset.forName("UTF-8"));
					HttpMessage.addHeader(headers, "Content-length: " + bytes.length);
					HttpMessage.addHeader(headers, "Content-type: text/html; charset=utf-8");
					body=ByteBuffer.wrap(bytes);
					
				}
				break;
			default:
				break;
		}
		
		return new HttpResponseMessage(code, protocol, headers, body);
	}

	public String generateSession(String userName, String userPass)
	{
		//System.out.println("SET:"+userName + userPass);
		String ans = Functions.md5(userName + Functions.md5(userPass));
		return ans;
	}
	
	public boolean login(ConnectionHandler ch, String userName, String userPass, String forumId)
	{
		try
		{
			String ans = forumProtocol.incomingMessage(Message.createMessage(Strings.LOG_IN, userName, userPass, forumId), ch);
			Parser p = new Parser(ans);
			p.Parse();
			
			if(!p.testHeader(Strings.LOGGED_IN)) return false;
			return true;
		}
		catch(Exception e)
		{
			return false;
		}
		
	}
	
	public boolean logout(ConnectionHandler ch)
	{
		try
		{
			String ans = forumProtocol.incomingMessage(Message.createMessage(Strings.LOGOUT), ch);
			Parser p = new Parser(ans);
			p.Parse();
			
			if(!p.testHeader(Strings.LOGGED_OUT)) return false;
			return true;
		}
		catch(Exception e)
		{
			return false;
		}
		
	}
	public String postReplyPage(ConnectionHandler ch, int topicId, String message)
	{
		try 
		{
			String idstr = this.session.get("userID");
			if(idstr == null) 
			{
				String ans = getTopicPage(ch, topicId);
				return ans.substring(0, ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\"Please login before posting.Thank you.\");</script></body></html>";
			}
			String ans;
			
			ans = forumProtocol.incomingMessage(Message.createMessage(Strings.ADD_REPLY, message, "" + topicId), ch);
			Parser p = new Parser(ans);
			p.Parse();
			if(p.testHeader(Strings.ERROR_ADD_REPLY))
			{
				ans = getTopicPage(ch, topicId);
				return ans.substring(0, ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\"" + p.argStr(1) + "\");</script></body></html>";
			}
			
			return getTopicPage(ch, topicId);
		}	
		catch (Exception e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return error404;
		}
		
	}
	
	public String newTopicPage(ConnectionHandler ch, int subForumId, String subject, String message)
	{
		try 
		{
			String idstr = this.session.get("userID");
			if(idstr == null) 
			{
				String ans = getSubForumPage(ch, subForumId);
				return ans.substring(0, ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\"Please login before posting.Thank you.\");</script></body></html>";
			}
			String ans;
			
			ans = forumProtocol.incomingMessage(Message.createMessage(Strings.ADD_TOPIC, subject, message, ""+subForumId), ch);
			Parser p = new Parser(ans);
			p.Parse();
			if(p.testHeader(Strings.ERROR_ADD_TOPIC))
			{
				ans = getSubForumPage(ch, subForumId);
				return ans.substring(0, ans.indexOf("</body>")) + "<script type=\"text/javascript\">alert(\"" + p.argStr(1) + "\");</script></body></html>";
			}
			int topicId = p.argInt(1);
			return getTopicPage(ch, topicId);
		}	
		catch (Exception e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return error404;
		}
		
	}
	
	public String ReplaceString(String html, String exp, String rep)
	{
		int pos = html.indexOf(exp);
		return html.substring(0, pos) + rep + html.substring(pos + exp.length());
	}
	
	public String getNewTopicPage(ConnectionHandler ch, int subForumId)
	{
		String main = new String(new_topic_html);
		
		
		String subForumName = Reactor.db.getSubForumByID(subForumId).getTitle();
		main = ReplaceString(main, "%SUBFORUMID%", "" + subForumId);
		main = ReplaceString(main, "%SUBFORUMID%", "" + subForumId);
		//main = ReplaceString(main, "%SUBFORUMID%", "" + subForumId);
		//main = ReplaceString(main, "%SUBFORUMID%", "" + subForumId);
		//main = ReplaceString(main, "%FORUMID%", "" + Reactor.db.getSubForumByID(subForumId).getParentForum());
		main = ReplaceString(main, "%SUBFORUMNAME%", subForumName);
		if(session.get("userID") == null) 
		{
			main = ReplaceString(main, "%SESSION%", "");
		}
		else
		{
			String logout = new String(logout_html);
			main = ReplaceString(main, "%SESSION%", logout);
			main = ReplaceString(main, "%REDIRECT%", "/");
			main = ReplaceString(main, "%USERNAME%", Reactor.db.getUserByID(Integer.parseInt(session.get("userID"))).getUsername());
		}
		Date date=new Date();
		main = ReplaceString(main, "%DATE%", date.toString());
		return main;
	}
	
	public String getNewReplyPage(ConnectionHandler ch, int topicId)
	{
		String main = new String(new_reply_html);
		
		int subForumId = Reactor.db.getSubForumIdByTopicId(topicId);
		String subForumName = Reactor.db.getSubForumByID(subForumId).getTitle();
		String topicName = Reactor.db.getPostByID(topicId).getTitle();
		main = ReplaceString(main, "%SUBFORUMID%", "" + subForumId);
		main = ReplaceString(main, "%SUBFORUMNAME%", subForumName);
		main = ReplaceString(main, "%TOPICID%", "" + topicId);
		main = ReplaceString(main, "%TOPICID%", "" + topicId);
		//main = ReplaceString(main, "%TOPICID%", "" + topicId);
		//main = ReplaceString(main, "%FORUMID%", "" + Reactor.db.getForumIdByTopicId(topicId));
		//main = ReplaceString(main, "%SUBFORUMID%", "" + subForumId);
		main = ReplaceString(main, "%TOPICNAME%", topicName);
		if(session.get("userID") == null) 
		{
			main = ReplaceString(main, "%SESSION%", "");
		}
		else
		{
			String logout = new String(logout_html);
			main = ReplaceString(main, "%SESSION%", logout);
			main = ReplaceString(main, "%REDIRECT%", "/");
			main = ReplaceString(main, "%USERNAME%", Reactor.db.getUserByID(Integer.parseInt(session.get("userID"))).getUsername());
		}
		
		Date date=new Date();
		main = ReplaceString(main, "%DATE%", date.toString());
		return main;
	}
	
	public String getTopicPage(ConnectionHandler ch, int topicId)
	{
		String main = new String(topic_html);
		try 
		{
			String ans = forumProtocol.incomingMessage(Message.createMessage(Strings.SHOW_MESSAGES, ""+topicId), ch);
			Parser p = new Parser(ans);
			p.Parse();
			String ins = "";
			if(!p.testHeader(Strings.ANS_SHOW_MESSAGES)) return error404;
			
			String threadBody = p.argStr(1);
			int threadAuthorId = p.argInt(3);
			String threadAuthor = p.argStr(4);
			
			int subForumId = Reactor.db.getSubForumIdByTopicId(topicId);
			String subForumName = Reactor.db.getSubForumByID(subForumId).getTitle();
			
			for(int i = 0; i < p.getSize(); i++) System.out.println(i + " " + p.argStr(i));
			
			//for all messages
			
			for(int i = 5; i < p.getSize(); i+=4)
			{
				//create entry
				
				String replyBody = p.argStr(i);
				int replyId = p.argInt(i+1);
				int replyAuthorId = p.argInt(i+2);
				String replyAuthor = p.argStr(i+3);
				String entry = new String(message_html);
				User u = Reactor.db.getUserByID(replyAuthorId);
				entry = ReplaceString(entry, "%TOPICNAME%", Reactor.db.getPostByID(topicId).getTitle());
				entry = ReplaceString(entry, "%REPLYBODY%", replyBody);
				entry = ReplaceString(entry, "%TOPICURL%", "/topic/" + topicId);
				entry = ReplaceString(entry, "%USERNAME%",  replyAuthor);
				entry = ReplaceString(entry, "%USERNAME%",  replyAuthor);
				entry = ReplaceString(entry, "%USERJOIN%",  u.getDay() + "." + u.getMonth() + "." + u.getYear());
				
				String cnt = forumProtocol.incomingMessage(Message.createMessage(Strings.GET_USER_MSGCOUNT, ""+replyAuthorId), ch);
				Parser pcnt = new Parser(cnt);
				pcnt.Parse();
				entry = ReplaceString(entry, "%NUMPOSTS%", pcnt.argStr(1));
				
				ins += entry;
			}
			
			main = ReplaceString(main, "%TOPICURL%", "/topic/" + topicId);
			main = ReplaceString(main, "%TOPICURL%", "/topic/" + topicId);
			main = ReplaceString(main, "%TOPICID%", "" + topicId);
			main = ReplaceString(main, "%TOPICID%", "" + topicId);
			main = ReplaceString(main, "%TOPICID%", "" + topicId);
			//main = ReplaceString(main, "%FORUMID%", "" + Reactor.db.getForumIdByTopicId(topicId));
			main = ReplaceString(main, "%TOPICNAME%", Reactor.db.getPostByID(topicId).getTitle());
			main = ReplaceString(main, "%TOPICNAME%", Reactor.db.getPostByID(topicId).getTitle());
			main = ReplaceString(main, "%TOPICNAME%", Reactor.db.getPostByID(topicId).getTitle());
			main = ReplaceString(main, "%USERNAME%", threadAuthor);
			main = ReplaceString(main, "%USERNAME%", threadAuthor);
			main = ReplaceString(main, "%REPLIES%", ins);
			main = ReplaceString(main, "%SUBFORUMID%", ""+subForumId);
			main = ReplaceString(main, "%SUBFORUMNAME%", subForumName);
			User u = Reactor.db.getUserByID(threadAuthorId);
			main = ReplaceString(main, "%USERJOIN%",  u.getDay() + "." + u.getMonth() + "." + u.getYear());
			
			String cnt = forumProtocol.incomingMessage(Message.createMessage(Strings.GET_USER_MSGCOUNT, ""+threadAuthorId), ch);
			Parser pcnt = new Parser(cnt);
			pcnt.Parse();
			main = ReplaceString(main, "%NUMPOSTS%", pcnt.argStr(1));
			Date date=new Date();
			main = ReplaceString(main, "%DATE%", date.toString());
			main = ReplaceString(main, "%THREADBODY%", threadBody);
			if(session.get("userID") == null) 
			{
				main = ReplaceString(main, "%SESSION%", "");
			}
			else
			{
				String logout = new String(logout_html);
				main = ReplaceString(main, "%SESSION%", logout);
				main = ReplaceString(main, "%REDIRECT%", "/");
				main = ReplaceString(main, "%USERNAME%", Reactor.db.getUserByID(Integer.parseInt(session.get("userID"))).getUsername());
			}
				
		} 
		catch (Exception e) 
		{
			//TODO: Crash HTML code
			e.printStackTrace();
		}
		//System.out.println(main);
		return main;
	
	}
	
	public String getSubForumPage(ConnectionHandler ch, int subForumId)
	{
		String main = new String(subforum_html);
		try 
		{
			String ans = forumProtocol.incomingMessage(Message.createMessage(Strings.SHOW_TOPICS, ""+subForumId), ch);
			Parser p = new Parser(ans);
			p.Parse();
			String ins = "";
			if(!p.testHeader(Strings.ANS_SHOW_TOPICS)) return error404;
			
			//for all topics
			for(int i = 1; i < p.getSize(); i+=2)
			{
				//create entry
				int topicId = p.argInt(i+1);
				String topicName = p.argStr(i);
				String entry = new String(topic_entry_html);
				Vector<Reply> replies = Reactor.db.getPostReplies(topicId);
				if(!replies.isEmpty())
				{
					User u = Reactor.db.getUserByID(replies.lastElement().getUserID());
					entry = ReplaceString(entry, "%LASTREPLYNAME%", u.getUsername());
				}
				else entry = ReplaceString(entry, "%LASTREPLYNAME%", "Nobody");
				entry = ReplaceString(entry, "%TOPICID%", ""+topicId);
				entry = ReplaceString(entry, "%TOPICNAME%", topicName);
				entry = ReplaceString(entry, "%NUMREPLIES%", ""+ForumSystemImpl.getRepliersOfPost(topicId).size());
				
				
				ins += entry;
			}
			main = ReplaceString(main, "%ENTRIES%", ins);
			Date date=new Date();
			main = ReplaceString(main, "%DATE%", date.toString());
			main = ReplaceString(main, "%SUBFORUMNAME%", Reactor.db.getSubForumByID(subForumId).getTitle());
			main = ReplaceString(main, "%SUBFORUMNAME%", Reactor.db.getSubForumByID(subForumId).getTitle());
			main = ReplaceString(main, "%SUBFORUMID%", ""+Reactor.db.getSubForumByID(subForumId).getId());
			main = ReplaceString(main, "%SUBFORUMID%", ""+Reactor.db.getSubForumByID(subForumId).getId());
			//main = ReplaceString(main, "%FORUMID%", ""+);
			if(session.get("userID") == null) 
			{
				main = ReplaceString(main, "%SESSION%", "");
			}
			else
			{
				String logout = new String(logout_html);
				main = ReplaceString(main, "%SESSION%", logout);
				main = ReplaceString(main, "%REDIRECT%", "/");
				main = ReplaceString(main, "%USERNAME%", Reactor.db.getUserByID(Integer.parseInt(session.get("userID"))).getUsername());
			}	
			
		} 
		catch (Exception e) 
		{
			//TODO: Crash HTML code
			e.printStackTrace();
		}
		//System.out.println(main);
		return main;
	
	}
	
	public String getForumSystemPage(ConnectionHandler ch)
	{
		String main = new String(forumsystem_html);
		Pair pair=null;
		try 
		{
			String ans = forumProtocol.incomingMessage(Message.createMessage(Strings.SHOW_FORUMS), ch);
			Parser p = new Parser(ans);
			p.Parse();
			String ins = "";
			if(!p.testHeader(Strings.ANS_SHOW_FORUMS)) return error404;
			
			Vector<Pair> forums=new Vector<Pair>();
			
			//for all forums
			for(int i = 1; i < p.getSize(); i+=2)
			{
				//create table
				int forumId = p.argInt(i+1);
				String forumName = p.argStr(i);
				pair=new Pair(forumName, forumId);
				forums.add(pair);
				String entry = new String(forum_entry_html);
				
				
				String ans2 = forumProtocol.incomingMessage(Message.createMessage(Strings.SHOW_SUBFORUMS, ""+forumId), ch);
				Parser p2 = new Parser(ans2);
				p2.Parse();
				
				String ins2 = "";
				//for all subforums of this forum
				for(int j = 1; j < p2.getSize(); j += 2)
				{
					int subForumId = p2.argInt(j+1);
					String subForumName = p2.argStr(j);
					String sub_entry = new String(subforum_entry_html);
					sub_entry = ReplaceString(sub_entry, "%SUBFORUMNAME%", subForumName);
					sub_entry = ReplaceString(sub_entry, "%SUBFORUMID%", ""+subForumId);
					sub_entry = ReplaceString(sub_entry, "%NUMTOPICS%", ""+ForumSystemImpl.getSubForumPostCount(subForumId));
					sub_entry = ReplaceString(sub_entry, "%NUMPOSTS%", ""+ForumSystemImpl.getSubForumPostPlusRepliesCount(subForumId));
					sub_entry = ReplaceString(sub_entry, "%LASTPOST%", ""+Reactor.db.getSubForumLastPost(subForumId));
					ins2 += sub_entry;
				}
				
				entry = ReplaceString(entry, "%ENTRIES%", ins2);
				entry = ReplaceString(entry, "%FORUMNAME%", forumName);
				ins += entry;
			}
			main = ReplaceString(main, "%ENTRIES%", ins);
			
			if(session.get("userID") == null) 
			{
				String login = new String(loginsystem_html);
				main = ReplaceString(main, "%SESSION%", login);
			}
			else
			{
				String logout = new String(logout_html);
				main = ReplaceString(main, "%SESSION%", logout);
				main = ReplaceString(main, "%REDIRECT%", "/");
				main = ReplaceString(main, "%USERNAME%", Reactor.db.getUserByID(Integer.parseInt(session.get("userID"))).getUsername());
			}
			Date date=new Date();
			main = ReplaceString(main, "%DATE%", date.toString());
			
			String combo = "<select name='forumid'>";
			for (int i = 0; i < forums.size(); i++) {
				combo+="<option name='fname' value='"+forums.get(i).getId()+"'>";
				combo+=forums.get(i).getForum();
				combo+="</option>";
			}
			combo+="</select>";
			
			main = ReplaceString(main, "%TALBOX%", combo);
			
		} 
		catch (Exception e) 
		{
			//TODO: Crash HTML code
			e.printStackTrace();
		}
		//System.out.println(main);
		return main;
	}
	
	
	/**
	 * In HTTP we can always close the connection after answering the client and this is what we do by returning true here.
	 */
	
	public boolean isEnd(HttpMessage msg) 
	{
		return true;
	}

	public boolean shouldClose() 
	{
		return this._shouldClose;
	}

	public void connectionTerminated() 
	{
		this._connectionTerminated = true;
	}

	
}
